package com.ruoyi.business.controller;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.business.domain.SysOcr;
import com.ruoyi.common.utils.DateUtils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.ocr.v20181119.OcrClient;
import com.tencentcloudapi.ocr.v20181119.models.GeneralBasicOCRRequest;
import com.tencentcloudapi.ocr.v20181119.models.GeneralBasicOCRResponse;
import com.tencentcloudapi.ocr.v20181119.models.TextDetection;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.AcContractInfo;
import com.ruoyi.business.service.IAcContractInfoService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 合同台账Controller
 *
 * @author ruoyi
 * @date 2025-02-18
 */
@RestController
@RequestMapping("/business/contractInfo")
public class AcContractInfoController extends BaseController
{
    @Autowired
    private IAcContractInfoService acContractInfoService;

    /**
     * 查询合同台账列表
     */
    @PreAuthorize("@ss.hasPermi('business:contractInfo:list')")
    @GetMapping("/list")
    public TableDataInfo list(AcContractInfo acContractInfo)
    {
        startPage();
        List<AcContractInfo> list = acContractInfoService.selectAcContractInfoList(acContractInfo);
        return getDataTable(list);
    }

    @GetMapping("/seasonList")
    public List<AcContractInfo> selectAcContractInfoSeasonList(AcContractInfo acContractInfo)
    {
        List<AcContractInfo> list = acContractInfoService.selectAcContractInfoSeasonList(acContractInfo);
        return list;
    }



    @GetMapping("/monthList")
    public List<AcContractInfo> monthList(AcContractInfo acContractInfo)
    {
        List<AcContractInfo> list = acContractInfoService.selectAcContractInfoMonthList(acContractInfo);
        return list;
    }



    /**
     * 查询合同台账列表
     */
    @PreAuthorize("@ss.hasPermi('business:contractInfo:list')")
    @GetMapping("/listSelect")
    public TableDataInfo listSelect(AcContractInfo acContractInfo)
    {
//        startPage();
        List<AcContractInfo> list = acContractInfoService.selectAcContractInfoList(acContractInfo);
        return getDataTable(list);
    }

    /**
     * 导出合同台账列表
     */
    @PreAuthorize("@ss.hasPermi('business:contractInfo:export')")
    @Log(title = "合同台账", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, AcContractInfo acContractInfo)
    {
        List<AcContractInfo> list = acContractInfoService.selectAcContractInfoList(acContractInfo);
        ExcelUtil<AcContractInfo> util = new ExcelUtil<AcContractInfo>(AcContractInfo.class);
        util.exportExcel(response, list, "合同台账数据");
    }

    /**
     * 获取合同台账详细信息
     */
    @PreAuthorize("@ss.hasPermi('business:contractInfo:query')")
    @GetMapping(value = "/{contractId}")
    public AjaxResult getInfo(@PathVariable("contractId") Long contractId)
    {
        return success(acContractInfoService.selectAcContractInfoByContractId(contractId));
    }

    /**
     * 新增合同台账
     */
//    @PreAuthorize("@ss.hasPermi('business:contractInfo:add')")
    @Log(title = "合同台账", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody AcContractInfo acContractInfo)
    {
        return toAjax(acContractInfoService.insertAcContractInfo(acContractInfo));
    }

    /**
     * 修改合同台账
     */
    @PreAuthorize("@ss.hasPermi('business:contractInfo:edit')")
    @Log(title = "合同台账", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody AcContractInfo acContractInfo)
    {
        return toAjax(acContractInfoService.updateAcContractInfo(acContractInfo));
    }

    /**
     * 删除合同台账
     */
    @PreAuthorize("@ss.hasPermi('business:contractInfo:remove')")
    @Log(title = "合同台账", businessType = BusinessType.DELETE)
	@DeleteMapping("/{contractIds}")
    public AjaxResult remove(@PathVariable Long[] contractIds)
    {
        return toAjax(acContractInfoService.deleteAcContractInfoByContractIds(contractIds));
    }

    //将pdf文件按照页数拆分并且转化base64格式

    @PostMapping("/splitPdfToBase64")
    public AcContractInfo splitPdfToBase64(@RequestParam("file") MultipartFile file) {
        List<String> base64List = new ArrayList<>();
        List<String> contentList = new ArrayList<>();
        AcContractInfo acContractInfo = new AcContractInfo();

        try (PDDocument document = PDDocument.load(file.getInputStream())) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            for (int pageIndex = 0; pageIndex < document.getNumberOfPages(); pageIndex++) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(pageIndex, 300, ImageType.RGB);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(bim, "png", baos);
                byte[] imageBytes = baos.toByteArray();
                String base64Image = Base64.getEncoder().encodeToString(imageBytes);
                SysOcr sysOcr = new SysOcr();
                sysOcr.setImageBase(base64Image);
                String content = getBase(sysOcr);
                contentList.add(content);
                base64List.add(base64Image);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 合并所有文本内容
        String fullText = String.join("", contentList);
        // 提取路明
        String tenantName =extractTenantName(fullText);

        // 提取日期和金额
       Map map = extractContractDetails(fullText);
       acContractInfo.setContractCustomerName(tenantName);
//       acContractInfo.setContractStartDate(map.get("startDate").toString());
        // 定义原始日期格式
        DateTimeFormatter originalFormatter = DateTimeFormatter.ofPattern("yyyy年M月d日");
        // 定义目标日期格式
        DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 解析原始日期字符串
        LocalDate localDate = LocalDate.parse(map.get("endDate").toString(), originalFormatter);
        // 转换为目标格式字符串
        String formattedEndDate = localDate.format(targetFormatter);

        LocalDate startDate = LocalDate.parse(map.get("startDate").toString(), originalFormatter);
        // 转换为目标格式字符串
        String formattedStartDate = startDate.format(targetFormatter);

        // 这里假设存在 setContractEndDate 方法，根据实际情况修改
        acContractInfo.setContractEndDate(DateUtils.parseDate(formattedEndDate));

        acContractInfo.setContractStartDate(DateUtils.parseDate(formattedStartDate));

        acContractInfo.setContractRent(new BigDecimal(map.get("yearRent").toString()));
        acContractInfo.setContractCashPledge(new BigDecimal(map.get("deposit").toString()));
        acContractInfo.setRemark(fullText);
        return acContractInfo;
    }


    private static String  extractTenantName(String text) {
        Pattern pattern = Pattern.compile("承租方[:：]\\s*(路明)\\s*\\(以下称乙方\\)");
        Matcher matcher = pattern.matcher(text);
        if (matcher.find()) {
            System.out.println("承租人姓名: " + matcher.group(1));
        } else {
            System.out.println("未找到承租人姓名");
        }
        return matcher.group(1);
    }

    private static Map extractContractDetails(String text) {

        Map<String,String> map = new HashMap();
        // 提取开始日期
        extractDate(text, "自(\\d{4}年\\d{1,2}月\\d{1,2}日)起", "租赁开始日期");

        // 提取结束日期
        extractDate(text, "至(\\d{4}年\\d{1,2}月\\d{1,2}日)止", "租赁结束日期");

        // 提取年租金
        extractAmount(text, "租金上打租为:每年(\\d+)元整", "年租金");

        // 提取保证金
        extractAmount(text, "房屋租赁保证金人民币(\\d+)元", "保证金");
        map.put("startDate",extractDate(text, "自(\\d{4}年\\d{1,2}月\\d{1,2}日)起", "租赁开始日期"));
        map.put("endDate",extractDate(text, "至(\\d{4}年\\d{1,2}月\\d{1,2}日)止", "租赁结束日期"));
        map.put("yearRent",extractAmount(text, "租金上打租为:每年(\\d+)元整", "年租金"));
        map.put("deposit",extractAmount(text, "房屋租赁保证金人民币(\\d+)元", "保证金"));
        return map;

    }

    private static String  extractDate(String text, String regex, String label) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);
        if (matcher.find()) {
            System.out.println(label + ": " + matcher.group(1));
        } else {
            System.out.println("未找到" + label);
        }
        return  matcher.group(1);
    }

    private static String  extractAmount(String text, String regex, String label) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);
        if (matcher.find()) {
            System.out.println(label + ": " + matcher.group(1) + "元");
        } else {
            System.out.println("未找到" + label);
        }
       return matcher.group(1);
    }


    //主要逻辑操作
    @PostMapping("/ocrPdf")
    public String getBase(SysOcr sysOcr) {
        try{
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential("AKIDFMH0lR4Vix6JOsIhiX9XkkYEl5C8rPTO", "mKhsqcDj2scAmIdVGqHXghZyFMJ8xeJq");
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile);


            // 实例化一个请求对象,每个接口都会对应一个request对象
            GeneralBasicOCRRequest req = new GeneralBasicOCRRequest();
            req.setImageBase64(sysOcr.getImageBase());
            // 返回的resp是一个GeneralBasicOCRResponse的实例，与请求对象对应
            GeneralBasicOCRResponse resp = client.GeneralBasicOCR(req);
            // 输出json格式的字符串回包
            System.out.println(GeneralBasicOCRResponse.toJsonString(resp));

            /*
             * 将内容取出
             * */
            TextDetection[] textDetections = resp.getTextDetections();
            TextDetection[] data = new TextDetection[textDetections.length]; // 初始化数组
            System.out.println(textDetections[0].getDetectedText());
            for (int i = 0; i < textDetections.length; i++) {
                data[i] = textDetections[i];
            }
            System.out.println(data);
// 直接打印数组（仅显示对象引用，不推荐）
            System.out.println(Arrays.toString(data));

// 更好的方式：提取文本内容后打印
            String[] texts = Arrays.stream(data)
                    .map(TextDetection::getDetectedText)
                    .toArray(String[]::new);
            String content = Arrays.toString(texts);
            content = content.replace(",","");
            content = content.replace("_","");
            content = content.replace(" ","");
            content = content.replace("扫描全能王创建]","");
            System.out.println("所有识别文本: " + content);
            return content;
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            return e.toString();
        }
    }


    /**
     * 拆分PDF文件为每页图片并转换为Base64格式，然后进行OCR识别，返回第一个识别文本
     *
     * @param file 待处理的PDF文件
     * @return 第一个识别出的文本内容，如果出错则返回错误信息
     */
    @PostMapping("/splitAndOcrPdf")
    public String splitAndOcrPdf(@RequestParam("file") MultipartFile file) {
        try (PDDocument document = PDDocument.load(file.getInputStream())) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential("AKIDFMH0lR4Vix6JOsIhiX9XkkYEl5C8rPTO", "mKhsqcDj2scAmIdVGqHXghZyFMJ8xeJq");
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile);

            for (int pageIndex = 0; pageIndex < document.getNumberOfPages(); pageIndex++) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(pageIndex, 300, ImageType.RGB);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(bim, "png", baos);
                byte[] imageBytes = baos.toByteArray();
                String base64Image = Base64.getEncoder().encodeToString(imageBytes);

                // 实例化一个请求对象,每个接口都会对应一个request对象
                GeneralBasicOCRRequest req = new GeneralBasicOCRRequest();
                req.setImageBase64(base64Image);
                // 返回的resp是一个GeneralBasicOCRResponse的实例，与请求对象对应
                GeneralBasicOCRResponse resp = client.GeneralBasicOCR(req);
                // 输出json格式的字符串回包
                System.out.println(GeneralBasicOCRResponse.toJsonString(resp));

                TextDetection[] textDetections = resp.getTextDetections();
                if (textDetections.length > 0) {
                    return textDetections[0].getDetectedText();
                }
            }
        } catch (IOException | TencentCloudSDKException e) {
            e.printStackTrace();
            return e.getMessage();
        }
        return "未识别到有效文本";
    }
}
